{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "1VMXUhJxtj1t"
   },
   "source": [
    "## Import modules"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "iAfdhVt_f146"
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "from matplotlib import pyplot as plt\n",
    "\n",
    "################################### for generating synthetic data\n",
    "from scipy.stats import lognorm,gamma\n",
    "from scipy.optimize import brentq\n",
    "\n",
    "################################### for neural network modeling\n",
    "import tensorflow as tf\n",
    "import tensorflow.keras as keras\n",
    "from tensorflow.keras import layers\n",
    "from tensorflow.keras import backend as K\n",
    "from tensorflow.keras.models import Model"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "3xdO9Otdd21H"
   },
   "source": [
    "## Routines to generate synthetic data\n",
    "Each function returns a sequence of event times and the average negative log-likelihood of the true model. \n",
    "Please see the main text for details of each model."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "sf1IByutd1zV"
   },
   "outputs": [],
   "source": [
    "######################################################\n",
    "### stationary poisson process\n",
    "######################################################\n",
    "def generate_stationary_poisson():\n",
    "    tau = np.random.exponential(size=100000)\n",
    "    T = tau.cumsum()\n",
    "    score = 1\n",
    "    return [T,score]\n",
    "\n",
    "######################################################\n",
    "### non-stationary poisson process\n",
    "######################################################\n",
    "def generate_nonstationary_poisson():\n",
    "    L = 20000\n",
    "    amp = 0.99\n",
    "    l_t = lambda t: np.sin(2*np.pi*t/L)*amp + 1\n",
    "    l_int = lambda t1,t2: - L/(2*np.pi)*( np.cos(2*np.pi*t2/L) - np.cos(2*np.pi*t1/L) )*amp   + (t2-t1)\n",
    "    \n",
    "    while 1:\n",
    "        T = np.random.exponential(size=210000).cumsum()*0.5\n",
    "        r = np.random.rand(210000)\n",
    "        index = r < l_t(T)/2.0\n",
    "        \n",
    "        if index.sum() > 100000:\n",
    "            T = T[index][:100000]\n",
    "            score = - ( np.log(l_t(T[80000:])).sum() - l_int(T[80000-1],T[-1]) )/20000\n",
    "            break\n",
    "       \n",
    "    return [T,score]\n",
    "\n",
    "######################################################\n",
    "### stationary renewal process\n",
    "######################################################\n",
    "def generate_stationary_renewal():\n",
    "    s = np.sqrt(np.log(6*6+1))\n",
    "    mu = -s*s/2\n",
    "    tau = lognorm.rvs(s=s,scale=np.exp(mu),size=100000)\n",
    "    lpdf = lognorm.logpdf(tau,s=s,scale=np.exp(mu))\n",
    "    T = tau.cumsum()\n",
    "    score = - np.mean(lpdf[80000:])\n",
    "    \n",
    "    return [T,score]\n",
    "   \n",
    "######################################################\n",
    "### non-stationary renewal process\n",
    "######################################################\n",
    "def generate_nonstationary_renewal():\n",
    "    L = 20000\n",
    "    amp = 0.99\n",
    "    l_t = lambda t: np.sin(2*np.pi*t/L)*amp + 1\n",
    "    l_int = lambda t1,t2: - L/(2*np.pi)*( np.cos(2*np.pi*t2/L) - np.cos(2*np.pi*t1/L) )*amp   + (t2-t1)\n",
    "\n",
    "    T = []\n",
    "    lpdf = []\n",
    "    x = 0\n",
    "\n",
    "    k = 4\n",
    "    rs = gamma.rvs(k,size=100000)\n",
    "    lpdfs = gamma.logpdf(rs,k)\n",
    "    rs = rs/k\n",
    "    lpdfs = lpdfs + np.log(k)\n",
    "\n",
    "    for i in range(100000):\n",
    "        x_next = brentq(lambda t: l_int(x,t) - rs[i],x,x+1000)\n",
    "        l = l_t(x_next)\n",
    "        T.append(x_next)\n",
    "        lpdf.append(  lpdfs[i] + np.log(l) )  \n",
    "        x = x_next\n",
    "\n",
    "    T = np.array(T)\n",
    "    lpdf = np.array(lpdf)\n",
    "    score = - lpdf[80000:].mean()\n",
    "    \n",
    "    return [T,score]\n",
    " \n",
    "######################################################\n",
    "### self-correcting process\n",
    "######################################################\n",
    "def generate_self_correcting():\n",
    "    \n",
    "    def self_correcting_process(mu,alpha,n):\n",
    "    \n",
    "        t = 0; x = 0;\n",
    "        T = [];\n",
    "        log_l = [];\n",
    "        Int_l = [];\n",
    "    \n",
    "        for i in range(n):\n",
    "            e = np.random.exponential()\n",
    "            tau = np.log( e*mu/np.exp(x) + 1 )/mu # e = ( np.exp(mu*tau)- 1 )*np.exp(x) /mu\n",
    "            t = t+tau\n",
    "            T.append(t)\n",
    "            x = x + mu*tau\n",
    "            log_l.append(x)\n",
    "            Int_l.append(e)\n",
    "            x = x -alpha\n",
    "\n",
    "        return [np.array(T),np.array(log_l),np.array(Int_l)]\n",
    "    \n",
    "    [T,log_l,Int_l] = self_correcting_process(1,1,100000)\n",
    "    score = - ( log_l[80000:] - Int_l[80000:] ).sum() / 20000\n",
    "    \n",
    "    return [T,score]\n",
    "\n",
    "######################################################\n",
    "### Hawkes process\n",
    "######################################################\n",
    "def generate_hawkes1():\n",
    "    [T,LL] = simulate_hawkes(100000,0.2,[0.8,0.0],[1.0,20.0])\n",
    "    score = - LL[80000:].mean()\n",
    "    return [T,score]\n",
    "\n",
    "def generate_hawkes2():\n",
    "    [T,LL] = simulate_hawkes(100000,0.2,[0.4,0.4],[1.0,20.0])\n",
    "    score = - LL[80000:].mean()\n",
    "    return [T,score]\n",
    "\n",
    "def simulate_hawkes(n,mu,alpha,beta):\n",
    "    T = []\n",
    "    LL = []\n",
    "    \n",
    "    x = 0\n",
    "    l_trg1 = 0\n",
    "    l_trg2 = 0\n",
    "    l_trg_Int1 = 0\n",
    "    l_trg_Int2 = 0\n",
    "    mu_Int = 0\n",
    "    count = 0\n",
    "    \n",
    "    while 1:\n",
    "        l = mu + l_trg1 + l_trg2\n",
    "        step = np.random.exponential()/l\n",
    "        x = x + step\n",
    "        \n",
    "        l_trg_Int1 += l_trg1 * ( 1 - np.exp(-beta[0]*step) ) / beta[0]\n",
    "        l_trg_Int2 += l_trg2 * ( 1 - np.exp(-beta[1]*step) ) / beta[1]\n",
    "        mu_Int += mu * step\n",
    "        l_trg1 *= np.exp(-beta[0]*step)\n",
    "        l_trg2 *= np.exp(-beta[1]*step)\n",
    "        l_next = mu + l_trg1 + l_trg2\n",
    "        \n",
    "        if np.random.rand() < l_next/l: #accept\n",
    "            T.append(x)\n",
    "            LL.append( np.log(l_next) - l_trg_Int1 - l_trg_Int2 - mu_Int )\n",
    "            l_trg1 += alpha[0]*beta[0]\n",
    "            l_trg2 += alpha[1]*beta[1]\n",
    "            l_trg_Int1 = 0\n",
    "            l_trg_Int2 = 0\n",
    "            mu_Int = 0\n",
    "            count += 1\n",
    "            \n",
    "            if count == n:\n",
    "                break\n",
    "        \n",
    "    return [np.array(T),np.array(LL)]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "AQ1JNV76w5X2"
   },
   "source": [
    "## Routines for neural network modeling"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "4gxV7yPb-T8p"
   },
   "outputs": [],
   "source": [
    "######################################################\n",
    "### constant hazard function\n",
    "######################################################\n",
    "class HAZARD_const():\n",
    "    \n",
    "    class Layer_LL(layers.Layer):\n",
    "\n",
    "        def __init__(self, **kwargs):\n",
    "            super(HAZARD_const.Layer_LL, self).__init__(**kwargs)\n",
    "\n",
    "        def build(self, input_shape):\n",
    "            self.build = True\n",
    "\n",
    "        def call(self, inputs):\n",
    "            x = inputs[0]; p = inputs[1];\n",
    "            log_l = p\n",
    "            Int_l = K.exp( p ) * x\n",
    "            return [log_l,Int_l]\n",
    "\n",
    "        def compute_output_shape(self, input_shape):\n",
    "            return [input_shape[0],input_shape[0]]\n",
    "               \n",
    "    def __call__(self,inputs):\n",
    "        x = inputs[0]; rnn = inputs[1];\n",
    "        p = layers.Dense(1)(rnn)\n",
    "        [log_l,Int_l] = HAZARD_const.Layer_LL()([x,p])\n",
    "        LL = layers.Subtract()([log_l,Int_l])\n",
    "        return [LL,log_l,Int_l]\n",
    "    \n",
    "######################################################\n",
    "### exponential hazard function\n",
    "######################################################\n",
    "class HAZARD_exp():\n",
    "    \n",
    "    class Layer_LL(layers.Layer):\n",
    "\n",
    "        def __init__(self, **kwargs):\n",
    "            super(HAZARD_exp.Layer_LL, self).__init__(**kwargs)\n",
    "\n",
    "        def build(self, input_shape):\n",
    "            self.a = self.add_weight(name='a', initializer= keras.initializers.Constant(value=1.0), shape=(), trainable=True)\n",
    "            self.build = True\n",
    "\n",
    "        def call(self, inputs):\n",
    "            x = inputs[0]; p = inputs[1];\n",
    "            a = self.a;\n",
    "            log_l = p - a*x\n",
    "            Int_l = K.exp( p ) * ( 1 - K.exp(-a*x) ) / a\n",
    "            return [log_l,Int_l]\n",
    "\n",
    "        def compute_output_shape(self, input_shape):\n",
    "            return [input_shape[0],input_shape[0]]\n",
    "               \n",
    "    def __call__(self,inputs):\n",
    "        x = inputs[0]; rnn = inputs[1];\n",
    "        p = layers.Dense(1)(rnn)\n",
    "        [log_l,Int_l] = HAZARD_exp.Layer_LL()([x,p])\n",
    "        LL = layers.Subtract()([log_l,Int_l])\n",
    "        return [LL,log_l,Int_l]\n",
    "\n",
    "######################################################\n",
    "### piecewise constant hazard function\n",
    "######################################################   \n",
    "class HAZARD_pc():\n",
    "    \n",
    "    class Layer_LL(layers.Layer):\n",
    "\n",
    "        def __init__(self, size_div,t_max,**kwargs):\n",
    "            self.size_div = size_div\n",
    "            self.t_max = t_max\n",
    "            self.bin_l = K.constant(np.linspace(0,t_max,size_div+1)[:-1].reshape(1,-1))\n",
    "            self.bin_r = K.constant(np.linspace(0,t_max,size_div+1)[1:].reshape(1,-1))\n",
    "            self.width = K.constant(t_max/size_div)\n",
    "            self.ones = K.constant(np.ones([size_div,1]))\n",
    "            super(HAZARD_pc.Layer_LL, self).__init__(**kwargs)\n",
    "\n",
    "        def build(self, input_shape):\n",
    "            self.build = True\n",
    "\n",
    "        def call(self, inputs):\n",
    "            x = inputs[0]; p = inputs[1];\n",
    "\n",
    "            r_le = K.cast( K.greater_equal(x,self.bin_l), dtype=K.floatx() ) \n",
    "            r_er = K.cast( K.less(         x,self.bin_r), dtype=K.floatx() )\n",
    "            r_e  = r_er*r_le\n",
    "            r_l  = 1-r_er\n",
    "            \n",
    "            log_l = K.log(K.dot(p*r_e,self.ones))\n",
    "            Int_l = K.dot(p*r_l*self.width,self.ones) + K.dot(p*(x-self.bin_l)*r_e,self.ones) \n",
    "\n",
    "            return [log_l,Int_l]\n",
    "\n",
    "        def compute_output(self,input_shape):\n",
    "            return [input_shape[0],input_shape[0],input_shape[0]]\n",
    "\n",
    "    def __init__(self,size_div,t_max):\n",
    "        self.size_div = size_div\n",
    "        self.t_max = t_max\n",
    "        \n",
    "    def __call__(self,inputs):\n",
    "        x = inputs[0]; rnn = inputs[1];\n",
    "        p = layers.Dense(self.size_div,activation='softplus')(rnn)\n",
    "        [log_l,Int_l] = HAZARD_pc.Layer_LL(self.size_div,self.t_max)([x,p])\n",
    "        LL = layers.Subtract()([log_l,Int_l])\n",
    "        return [LL,log_l,Int_l]\n",
    "    \n",
    "        \n",
    "######################################################\n",
    "### neural network based hazard function\n",
    "######################################################\n",
    "class HAZARD_NN():\n",
    "    \n",
    "    def __init__(self, size_layer, size_nn, log_mode=True):\n",
    "        self.size_layer = size_layer\n",
    "        self.size_nn = size_nn\n",
    "        self.log_mode = log_mode\n",
    "          \n",
    "    def __call__(self,inputs):\n",
    "        x = inputs[0]; rnn = inputs[1];\n",
    "        \n",
    "        if self.log_mode:\n",
    "            x_nmlz = layers.Lambda(lambda x: (K.log(x)-self.mu_x)/self.sigma_x )(x) \n",
    "        else:\n",
    "            x_nmlz = layers.Lambda(lambda x: (x-self.mu_x)/self.sigma_x )(x) \n",
    "            \n",
    "        def abs_glorot_uniform(shape, dtype=None, partition_info=None):\n",
    "            return K.abs(keras.initializers.glorot_uniform(seed=None)(shape,dtype=dtype))\n",
    "        \n",
    "        hidden_x = layers.Dense(self.size_nn,kernel_initializer=abs_glorot_uniform,kernel_constraint=keras.constraints.NonNeg(),use_bias=False)(x_nmlz)\n",
    "        hidden_p = layers.Dense(self.size_nn)(rnn)\n",
    "        hidden = layers.Add()([hidden_x,hidden_p])\n",
    "        hidden = layers.Activation('tanh')(hidden)\n",
    "        \n",
    "        for i in range(self.size_layer-1):\n",
    "            hidden = layers.Dense(self.size_nn,activation='tanh',kernel_initializer=abs_glorot_uniform,kernel_constraint=keras.constraints.NonNeg())(hidden)\n",
    "            \n",
    "        Int_l = layers.Dense(1, activation='softplus',kernel_initializer=abs_glorot_uniform, kernel_constraint=keras.constraints.NonNeg() )(hidden)\n",
    "        log_l = layers.Lambda(lambda inputs: K.log( 1e-10 + K.gradients(inputs[0],inputs[1])[0] ))([Int_l,x])\n",
    "        LL = layers.Subtract()([log_l,Int_l])\n",
    "        \n",
    "        return [LL,log_l,Int_l]\n",
    "        \n",
    "    def normalize_input(self,x):\n",
    "        \n",
    "        if self.log_mode:\n",
    "            self.mu_x = np.log(x).mean() \n",
    "            self.sigma_x = np.log(x).std()   \n",
    "        else:\n",
    "            self.mu_x = x.mean()\n",
    "            self.sigma_x = x.std()\n",
    "        \n",
    "        return self\n",
    "    \n",
    "\n",
    "######################################################\n",
    "### RNN\n",
    "######################################################\n",
    "class RNN_PP():\n",
    "    \n",
    "    def __init__(self, size_rnn, time_step, log_mode=True):\n",
    "        self.size_rnn= size_rnn\n",
    "        self.time_step = time_step\n",
    "        self.log_mode = log_mode\n",
    "        \n",
    "    def __call__(self,inputs):\n",
    "        x = inputs\n",
    "        \n",
    "        if self.log_mode:\n",
    "            x_nmlz = layers.Lambda(lambda x: (K.log(x)-self.mu_x)/self.sigma_x )(x) \n",
    "        else:\n",
    "            x_nmlz = layers.Lambda(lambda x: (x-self.mu_x)/self.sigma_x )(x) \n",
    "            \n",
    "        rnn = layers.SimpleRNN(self.size_rnn,input_shape=(self.time_step,1),activation='tanh')(x_nmlz)\n",
    "        \n",
    "        return rnn\n",
    "    \n",
    "    def normalize_input(self,x):\n",
    "        \n",
    "        if self.log_mode:\n",
    "            self.mu_x = np.log(x).mean() \n",
    "            self.sigma_x = np.log(x).std()   \n",
    "        else:\n",
    "            self.mu_x = x.mean()\n",
    "            self.sigma_x = x.std()\n",
    "        \n",
    "        return self\n",
    "    \n",
    "    \n",
    "######################################################################################\n",
    "### a class for a recurrent neural network based model for temporal point processes\n",
    "######################################################################################\n",
    "class NPP():\n",
    "    \n",
    "    def __init__(self,time_step,size_rnn,type_hazard,size_layer=2,size_nn=64,size_div=128,log_mode=True):\n",
    "        self.time_step = time_step\n",
    "        self.size_rnn = size_rnn\n",
    "        self.type_hazard = type_hazard\n",
    "        self.size_layer = size_layer\n",
    "        self.size_nn = size_nn\n",
    "        self.log_mode = log_mode\n",
    "        self.size_div = size_div\n",
    "            \n",
    "    def set_data(self,T):\n",
    "        \n",
    "        def rolling_matrix(x,window_size):\n",
    "            x = x.flatten()\n",
    "            n = x.shape[0]\n",
    "            stride = x.strides[0]\n",
    "            return np.lib.stride_tricks.as_strided(x, shape=(n-window_size+1, window_size), strides=(stride,stride) ).copy()\n",
    "\n",
    "        def transform_data(T,n_train,n_test,time_step):\n",
    "\n",
    "            np.random.seed(0)\n",
    "\n",
    "            index_shuffle = np.random.permutation(n_train-time_step-1)\n",
    "\n",
    "            dT_train = np.ediff1d(T[:n_train])\n",
    "            r_dT_train = rolling_matrix(dT_train,time_step+1)[index_shuffle]\n",
    "\n",
    "            dT_test = np.ediff1d(T[n_train-time_step-1:n_train+n_test])\n",
    "            r_dT_test = rolling_matrix(dT_test,time_step+1)\n",
    "\n",
    "            dT_train_input  = r_dT_train[:,:-1].reshape(-1,time_step,1)\n",
    "            dT_train_target = r_dT_train[:,[-1]]\n",
    "            dT_test_input  = r_dT_test[:,:-1].reshape(-1,time_step,1)\n",
    "            dT_test_target = r_dT_test[:,[-1]]\n",
    "\n",
    "            return [dT_train_input,dT_train_target,dT_test_input,dT_test_target]\n",
    "        \n",
    "        n = T.shape[0]       \n",
    "        [dT_train_input,dT_train_target,dT_test_input,dT_test_target] = transform_data(T,int(n*0.8),n-int(n*0.8),self.time_step) # A sequence is divided into training and test data.\n",
    "            \n",
    "        self.dT_train_input  = dT_train_input\n",
    "        self.dT_train_target = dT_train_target\n",
    "        self.dT_test_input   = dT_test_input\n",
    "        self.dT_test_target  = dT_test_target\n",
    "\n",
    "        self.n_train = dT_train_target.shape[0]\n",
    "        self.n_test  = dT_test_target.shape[0]\n",
    "        \n",
    "        self.t_max = np.max(np.vstack([self.dT_train_target,self.dT_test_target]))*1.001\n",
    "        \n",
    "        #print(\"n_train: %d, n_test: %d, t_max: %f\" % (self.n_train,self.n_test,self.t_max) )\n",
    "       \n",
    "        return self\n",
    "        \n",
    "    def set_model(self):\n",
    "        \n",
    "        if self.type_hazard == 'const':\n",
    "            self.layer_hazard = HAZARD_const()\n",
    "        elif self.type_hazard == 'exp':\n",
    "            self.layer_hazard = HAZARD_exp()\n",
    "        elif self.type_hazard == 'pc':\n",
    "            self.layer_hazard = HAZARD_pc(size_div=self.size_div,t_max=self.t_max)\n",
    "        elif self.type_hazard == 'NN':\n",
    "            self.layer_hazard = HAZARD_NN(size_layer=self.size_layer,size_nn=self.size_nn,log_mode=self.log_mode).normalize_input(self.dT_train_target)\n",
    "        \n",
    "        self.rnn = RNN_PP(size_rnn=self.size_rnn,time_step=self.time_step,log_mode=self.log_mode).normalize_input(self.dT_train_target)\n",
    "        \n",
    "        input_dT = layers.Input(shape=(self.time_step,1))\n",
    "        input_x = layers.Input(shape=(1,))\n",
    "        output_rnn = self.rnn(input_dT)\n",
    "        [LL,log_l,Int_l] = self.layer_hazard([input_x,output_rnn])\n",
    "        self.model = Model(inputs=[input_dT,input_x],outputs=[LL,log_l,Int_l])\n",
    "        self.model.add_loss(-K.mean(LL))\n",
    "        #model.summary()      \n",
    "        \n",
    "        return self\n",
    "    \n",
    "    def compile(self,lr=1e-3):\n",
    "        self.model.compile(keras.optimizers.Adam(lr=lr))\n",
    "        return self\n",
    "    \n",
    "    def scores(self):\n",
    "        scores = - self.model.predict([self.dT_test_input,self.dT_test_target],batch_size=self.n_test)[0].flatten()\n",
    "        return scores\n",
    "    \n",
    "    class CustomEarlyStopping(keras.callbacks.Callback):\n",
    "    \n",
    "        def __init__(self):\n",
    "            super(NPP.CustomEarlyStopping, self).__init__()\n",
    "            self.best_val_loss = 100000\n",
    "            self.history_val_loss = []\n",
    "            self.best_weights   = None\n",
    "\n",
    "        def on_epoch_end(self, epoch, logs=None):\n",
    "            \n",
    "            val_loss = logs['val_loss']\n",
    "            self.history_val_loss = np.append(self.history_val_loss,val_loss)\n",
    "\n",
    "            if val_loss < self.best_val_loss:\n",
    "                self.best_val_loss = val_loss\n",
    "                self.best_weights = self.model.get_weights()\n",
    "                \n",
    "            if self.best_val_loss + 0.05 < val_loss: \n",
    "                    self.model.stop_training = True\n",
    "                \n",
    "            if (epoch+1) % 5 == 0:\n",
    "                \n",
    "                #print('epoch: %d, current_val_loss: %f, min_val_loss: %f' % (epoch+1,val_loss,self.best_val_loss) )\n",
    "                \n",
    "                if (epoch+1) >= 15:\n",
    "                    if self.best_val_loss > self.history_val_loss[:-5].min() - 0.001: \n",
    "                        self.model.stop_training = True\n",
    "                        \n",
    "        def on_train_end(self,logs=None):\n",
    "            self.model.set_weights(self.best_weights)\n",
    "            #print('set optimal weights')\n",
    "        \n",
    "    def fit_eval(self,epochs=100,batch_size=256):\n",
    "        \n",
    "        es = NPP.CustomEarlyStopping()\n",
    "        history = self.model.fit([self.dT_train_input,self.dT_train_target],epochs=epochs,batch_size=batch_size,validation_split=0.2,verbose=0,callbacks=[es])\n",
    "        scores = self.scores()\n",
    "        \n",
    "        self.history = {'loss':np.array(history.history['loss']), 'val_loss':np.array(history.history['val_loss'])}\n",
    "        self.val_loss = es.best_val_loss\n",
    "        self.score = scores.mean()\n",
    "        \n",
    "        #print('score: %f' % scores.mean() )\n",
    "        #print()\n",
    "            \n",
    "        return self\n",
    "    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "VZ-4bLLay-pu"
   },
   "source": [
    "## demo\n",
    "A python class \"NPP\" splits the data into training and test data, trains the model using the training data, and evaluates the model using the test data."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 684
    },
    "colab_type": "code",
    "executionInfo": {
     "elapsed": 214545,
     "status": "ok",
     "timestamp": 1558482021830,
     "user": {
      "displayName": "O3 T",
      "photoUrl": "",
      "userId": "04273384571780432640"
     },
     "user_tz": -540
    },
    "id": "kaTsj3QPkIxR",
    "outputId": "83ba8772-f3d0-4353-abf5-91fe5124d1d0"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "#######################################\n",
      "## Stationary Poisson process\n",
      "#######################################\n",
      "\n",
      "WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/resource_variable_ops.py:435: colocate_with (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Colocations handled automatically by placer.\n",
      "WARNING:tensorflow:Output \"subtract\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"subtract\".\n",
      "WARNING:tensorflow:Output \"layer_ll\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll\".\n",
      "WARNING:tensorflow:Output \"layer_ll\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll\".\n",
      "WARNING:tensorflow:Output \"subtract_1\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"subtract_1\".\n",
      "WARNING:tensorflow:Output \"layer_ll_1\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_1\".\n",
      "WARNING:tensorflow:Output \"layer_ll_1\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_1\".\n",
      "WARNING:tensorflow:Output \"subtract_2\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"subtract_2\".\n",
      "WARNING:tensorflow:Output \"layer_ll_2\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_2\".\n",
      "WARNING:tensorflow:Output \"layer_ll_2\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_2\".\n",
      "WARNING:tensorflow:Output \"subtract_3\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"subtract_3\".\n",
      "WARNING:tensorflow:Output \"lambda_5\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"lambda_5\".\n",
      "WARNING:tensorflow:Output \"dense_6\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"dense_6\".\n",
      "WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/math_ops.py:3066: to_int32 (from tensorflow.python.ops.math_ops) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Use tf.cast instead.\n",
      "\n",
      "#######################################\n",
      "## Score\n",
      "#######################################\n",
      "## true model                 \n",
      " score for the test data: 1.000\n",
      "## constand model             \n",
      " score for the test data: 0.992 (standardized score: -0.008), loss for the validation data: 1.009\n",
      "## exponential model          \n",
      " score for the test data: 0.993 (standardized score: -0.007), loss for the validation data: 1.009\n",
      "## piecewise constant model   \n",
      " score for the test data: 0.996 (standardized score: -0.004), loss for the validation data: 1.013\n",
      "## neural network based model \n",
      " score for the test data: 0.994 (standardized score: -0.006), loss for the validation data: 1.010\n"
     ]
    }
   ],
   "source": [
    "########## Setup\n",
    "time_step = 20 # truncation depth of a RNN \n",
    "size_rnn = 64  # the number of units in a RNN\n",
    "size_div = 128 # the number of sub-intervals of the piecewise constant function (piecewise constant model)\n",
    "size_nn = 64   # the number of units in each hidden layer of the cumulative hazard function network (neural network based model)\n",
    "size_layer = 2 # the number of hidden layers of the cumulative hazard function network (neural network based model)\n",
    "\n",
    "########## Generate data\n",
    "[T,score_ref] = generate_stationary_poisson()     # generate synthetic data: stationary Poisson process.\n",
    "print('#######################################')\n",
    "print('## Stationary Poisson process')\n",
    "print('#######################################')\n",
    "print()\n",
    "\n",
    "\n",
    "########## Train and evaluate the model (The following code will raise warnings, but please ignore them.)\n",
    "\n",
    "# constant model\n",
    "npp1 = NPP(time_step=time_step,size_rnn=size_rnn,type_hazard='const').set_data(T).set_model().compile(lr=0.001).fit_eval(batch_size=256)\n",
    "\n",
    "# exponential model\n",
    "npp2 = NPP(time_step=time_step,size_rnn=size_rnn,type_hazard='exp').set_data(T).set_model().compile(lr=0.001).fit_eval(batch_size=256)\n",
    "\n",
    "# piecewise constant model\n",
    "npp3 = NPP(time_step=time_step,size_rnn=size_rnn,type_hazard='pc',size_div=size_div).set_data(T).set_model().compile(lr=0.001).fit_eval(batch_size=256)\n",
    "\n",
    "# neural network based model\n",
    "npp4 = NPP(time_step=time_step,size_rnn=size_rnn,type_hazard='NN',size_layer=size_layer,size_nn=size_nn).set_data(T).set_model().compile(lr=0.001).fit_eval(batch_size=256)\n",
    "\n",
    "print()\n",
    "print('#######################################')\n",
    "print('## Score')\n",
    "print('#######################################')\n",
    "print('## true model                 \\n score for the test data: %.3f' % score_ref)\n",
    "print('## constand model             \\n score for the test data: %.3f (standardized score: %.3f), loss for the validation data: %.3f' % (npp1.score,npp1.score-score_ref,npp1.val_loss) )\n",
    "print('## exponential model          \\n score for the test data: %.3f (standardized score: %.3f), loss for the validation data: %.3f' % (npp2.score,npp2.score-score_ref,npp2.val_loss) )\n",
    "print('## piecewise constant model   \\n score for the test data: %.3f (standardized score: %.3f), loss for the validation data: %.3f' % (npp3.score,npp3.score-score_ref,npp3.val_loss) )\n",
    "print('## neural network based model \\n score for the test data: %.3f (standardized score: %.3f), loss for the validation data: %.3f' % (npp4.score,npp4.score-score_ref,npp4.val_loss) )\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 577
    },
    "colab_type": "code",
    "executionInfo": {
     "elapsed": 459977,
     "status": "ok",
     "timestamp": 1558482267278,
     "user": {
      "displayName": "O3 T",
      "photoUrl": "",
      "userId": "04273384571780432640"
     },
     "user_tz": -540
    },
    "id": "CtDEvqsA5Vwe",
    "outputId": "be2b4051-acc2-4f4d-ba65-26fec0fc29cf"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "#######################################\n",
      "## Non-stationary Poisson process\n",
      "#######################################\n",
      "\n",
      "WARNING:tensorflow:Output \"subtract_4\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"subtract_4\".\n",
      "WARNING:tensorflow:Output \"layer_ll_3\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_3\".\n",
      "WARNING:tensorflow:Output \"layer_ll_3\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_3\".\n",
      "WARNING:tensorflow:Output \"subtract_5\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"subtract_5\".\n",
      "WARNING:tensorflow:Output \"layer_ll_4\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_4\".\n",
      "WARNING:tensorflow:Output \"layer_ll_4\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_4\".\n",
      "WARNING:tensorflow:Output \"subtract_6\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"subtract_6\".\n",
      "WARNING:tensorflow:Output \"layer_ll_5\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_5\".\n",
      "WARNING:tensorflow:Output \"layer_ll_5\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_5\".\n",
      "WARNING:tensorflow:Output \"subtract_7\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"subtract_7\".\n",
      "WARNING:tensorflow:Output \"lambda_11\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"lambda_11\".\n",
      "WARNING:tensorflow:Output \"dense_13\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"dense_13\".\n",
      "\n",
      "#######################################\n",
      "## Score\n",
      "#######################################\n",
      "## true model                 \n",
      " score for the test data: 0.701\n",
      "## constand model             \n",
      " score for the test data: 0.721 (standardized score: 0.020), loss for the validation data: 0.721\n",
      "## exponential model          \n",
      " score for the test data: 0.721 (standardized score: 0.020), loss for the validation data: 0.719\n",
      "## piecewise constant model   \n",
      " score for the test data: 0.722 (standardized score: 0.021), loss for the validation data: 0.720\n",
      "## neural network based model \n",
      " score for the test data: 0.722 (standardized score: 0.021), loss for the validation data: 0.722\n"
     ]
    }
   ],
   "source": [
    "########## Setup\n",
    "time_step = 20 # truncation depth of a RNN \n",
    "size_rnn = 64  # the number of units in a RNN\n",
    "size_div = 128 # the number of sub-intervals of the piecewise constant function (piecewise constant model)\n",
    "size_nn = 64   # the number of units in each hidden layer of the cumulative hazard function network (neural network based model)\n",
    "size_layer = 2 # the number of hidden layers of the cumulative hazard function network (neural network based model)\n",
    "\n",
    "########## Generate data\n",
    "[T,score_ref] = generate_nonstationary_poisson() # generate synthetic data: nonstationary Poisson process.\n",
    "print('#######################################')\n",
    "print('## Non-stationary Poisson process')\n",
    "print('#######################################')\n",
    "print()\n",
    "\n",
    "\n",
    "########## Train and evaluate the model (The following code will raise warnings, but please ignore them.)\n",
    "\n",
    "# constant model\n",
    "npp1 = NPP(time_step=time_step,size_rnn=size_rnn,type_hazard='const').set_data(T).set_model().compile(lr=0.001).fit_eval(batch_size=256)\n",
    "\n",
    "# exponential model\n",
    "npp2 = NPP(time_step=time_step,size_rnn=size_rnn,type_hazard='exp').set_data(T).set_model().compile(lr=0.001).fit_eval(batch_size=256)\n",
    "\n",
    "# piecewise constant model\n",
    "npp3 = NPP(time_step=time_step,size_rnn=size_rnn,type_hazard='pc',size_div=size_div).set_data(T).set_model().compile(lr=0.001).fit_eval(batch_size=256)\n",
    "\n",
    "# neural network based model\n",
    "npp4 = NPP(time_step=time_step,size_rnn=size_rnn,type_hazard='NN',size_layer=size_layer,size_nn=size_nn).set_data(T).set_model().compile(lr=0.001).fit_eval(batch_size=256)\n",
    "\n",
    "print()\n",
    "print('#######################################')\n",
    "print('## Score')\n",
    "print('#######################################')\n",
    "print('## true model                 \\n score for the test data: %.3f' % score_ref)\n",
    "print('## constand model             \\n score for the test data: %.3f (standardized score: %.3f), loss for the validation data: %.3f' % (npp1.score,npp1.score-score_ref,npp1.val_loss) )\n",
    "print('## exponential model          \\n score for the test data: %.3f (standardized score: %.3f), loss for the validation data: %.3f' % (npp2.score,npp2.score-score_ref,npp2.val_loss) )\n",
    "print('## piecewise constant model   \\n score for the test data: %.3f (standardized score: %.3f), loss for the validation data: %.3f' % (npp3.score,npp3.score-score_ref,npp3.val_loss) )\n",
    "print('## neural network based model \\n score for the test data: %.3f (standardized score: %.3f), loss for the validation data: %.3f' % (npp4.score,npp4.score-score_ref,npp4.val_loss) )\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 577
    },
    "colab_type": "code",
    "executionInfo": {
     "elapsed": 661560,
     "status": "ok",
     "timestamp": 1558482468878,
     "user": {
      "displayName": "O3 T",
      "photoUrl": "",
      "userId": "04273384571780432640"
     },
     "user_tz": -540
    },
    "id": "FA17ufjn5WVZ",
    "outputId": "f038310c-6ca6-46e7-b300-fec7b86e098e"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "#######################################\n",
      "## Stationary Renewal process\n",
      "#######################################\n",
      "\n",
      "WARNING:tensorflow:Output \"subtract_8\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"subtract_8\".\n",
      "WARNING:tensorflow:Output \"layer_ll_6\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_6\".\n",
      "WARNING:tensorflow:Output \"layer_ll_6\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_6\".\n",
      "WARNING:tensorflow:Output \"subtract_9\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"subtract_9\".\n",
      "WARNING:tensorflow:Output \"layer_ll_7\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_7\".\n",
      "WARNING:tensorflow:Output \"layer_ll_7\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_7\".\n",
      "WARNING:tensorflow:Output \"subtract_10\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"subtract_10\".\n",
      "WARNING:tensorflow:Output \"layer_ll_8\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_8\".\n",
      "WARNING:tensorflow:Output \"layer_ll_8\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_8\".\n",
      "WARNING:tensorflow:Output \"subtract_11\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"subtract_11\".\n",
      "WARNING:tensorflow:Output \"lambda_17\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"lambda_17\".\n",
      "WARNING:tensorflow:Output \"dense_20\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"dense_20\".\n",
      "\n",
      "#######################################\n",
      "## Score\n",
      "#######################################\n",
      "## true model                 \n",
      " score for the test data: 0.245\n",
      "## constand model             \n",
      " score for the test data: 1.034 (standardized score: 0.789), loss for the validation data: 1.040\n",
      "## exponential model          \n",
      " score for the test data: 0.546 (standardized score: 0.301), loss for the validation data: 0.586\n",
      "## piecewise constant model   \n",
      " score for the test data: 0.786 (standardized score: 0.541), loss for the validation data: 0.822\n",
      "## neural network based model \n",
      " score for the test data: 0.248 (standardized score: 0.002), loss for the validation data: 0.296\n"
     ]
    }
   ],
   "source": [
    "########## Setup\n",
    "time_step = 20 # truncation depth of a RNN \n",
    "size_rnn = 64  # the number of units in a RNN\n",
    "size_div = 128 # the number of sub-intervals of the piecewise constant function (piecewise constant model)\n",
    "size_nn = 64   # the number of units in each hidden layer of the cumulative hazard function network (neural network based model)\n",
    "size_layer = 2 # the number of hidden layers of the cumulative hazard function network (neural network based model)\n",
    "\n",
    "########## Generate data\n",
    "[T,score_ref] = generate_stationary_renewal()    # generate synthetic data: stationary renewal process.\n",
    "print('#######################################')\n",
    "print('## Stationary Renewal process')\n",
    "print('#######################################')\n",
    "print()\n",
    "\n",
    "\n",
    "########## Train and evaluate the model (The following code will raise warnings, but please ignore them.)\n",
    "\n",
    "# constant model\n",
    "npp1 = NPP(time_step=time_step,size_rnn=size_rnn,type_hazard='const').set_data(T).set_model().compile(lr=0.001).fit_eval(batch_size=256)\n",
    "\n",
    "# exponential model\n",
    "npp2 = NPP(time_step=time_step,size_rnn=size_rnn,type_hazard='exp').set_data(T).set_model().compile(lr=0.001).fit_eval(batch_size=256)\n",
    "\n",
    "# piecewise constant model\n",
    "npp3 = NPP(time_step=time_step,size_rnn=size_rnn,type_hazard='pc',size_div=size_div).set_data(T).set_model().compile(lr=0.001).fit_eval(batch_size=256)\n",
    "\n",
    "# neural network based model\n",
    "npp4 = NPP(time_step=time_step,size_rnn=size_rnn,type_hazard='NN',size_layer=size_layer,size_nn=size_nn).set_data(T).set_model().compile(lr=0.001).fit_eval(batch_size=256)\n",
    "\n",
    "print()\n",
    "print('#######################################')\n",
    "print('## Score')\n",
    "print('#######################################')\n",
    "print('## true model                 \\n score for the test data: %.3f' % score_ref)\n",
    "print('## constand model             \\n score for the test data: %.3f (standardized score: %.3f), loss for the validation data: %.3f' % (npp1.score,npp1.score-score_ref,npp1.val_loss) )\n",
    "print('## exponential model          \\n score for the test data: %.3f (standardized score: %.3f), loss for the validation data: %.3f' % (npp2.score,npp2.score-score_ref,npp2.val_loss) )\n",
    "print('## piecewise constant model   \\n score for the test data: %.3f (standardized score: %.3f), loss for the validation data: %.3f' % (npp3.score,npp3.score-score_ref,npp3.val_loss) )\n",
    "print('## neural network based model \\n score for the test data: %.3f (standardized score: %.3f), loss for the validation data: %.3f' % (npp4.score,npp4.score-score_ref,npp4.val_loss) )\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 577
    },
    "colab_type": "code",
    "executionInfo": {
     "elapsed": 920213,
     "status": "ok",
     "timestamp": 1558482727542,
     "user": {
      "displayName": "O3 T",
      "photoUrl": "",
      "userId": "04273384571780432640"
     },
     "user_tz": -540
    },
    "id": "m9FEiEaX5Wmc",
    "outputId": "2c499f65-1e20-4b40-83f1-3d9fc7f211f4"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "#######################################\n",
      "## Non-tationary Renewal process\n",
      "#######################################\n",
      "\n",
      "WARNING:tensorflow:Output \"subtract_12\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"subtract_12\".\n",
      "WARNING:tensorflow:Output \"layer_ll_9\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_9\".\n",
      "WARNING:tensorflow:Output \"layer_ll_9\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_9\".\n",
      "WARNING:tensorflow:Output \"subtract_13\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"subtract_13\".\n",
      "WARNING:tensorflow:Output \"layer_ll_10\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_10\".\n",
      "WARNING:tensorflow:Output \"layer_ll_10\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_10\".\n",
      "WARNING:tensorflow:Output \"subtract_14\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"subtract_14\".\n",
      "WARNING:tensorflow:Output \"layer_ll_11\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_11\".\n",
      "WARNING:tensorflow:Output \"layer_ll_11\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_11\".\n",
      "WARNING:tensorflow:Output \"subtract_15\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"subtract_15\".\n",
      "WARNING:tensorflow:Output \"lambda_23\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"lambda_23\".\n",
      "WARNING:tensorflow:Output \"dense_27\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"dense_27\".\n",
      "\n",
      "#######################################\n",
      "## Score\n",
      "#######################################\n",
      "## true model                 \n",
      " score for the test data: 0.340\n",
      "## constand model             \n",
      " score for the test data: 0.707 (standardized score: 0.367), loss for the validation data: 0.703\n",
      "## exponential model          \n",
      " score for the test data: 0.691 (standardized score: 0.351), loss for the validation data: 0.692\n",
      "## piecewise constant model   \n",
      " score for the test data: 0.676 (standardized score: 0.335), loss for the validation data: 0.673\n",
      "## neural network based model \n",
      " score for the test data: 0.365 (standardized score: 0.025), loss for the validation data: 0.358\n"
     ]
    }
   ],
   "source": [
    "########## Setup\n",
    "time_step = 20 # truncation depth of a RNN \n",
    "size_rnn = 64  # the number of units in a RNN\n",
    "size_div = 128 # the number of sub-intervals of the piecewise constant function (piecewise constant model)\n",
    "size_nn = 64   # the number of units in each hidden layer of the cumulative hazard function network (neural network based model)\n",
    "size_layer = 2 # the number of hidden layers of the cumulative hazard function network (neural network based model)\n",
    "\n",
    "########## Generate data\n",
    "[T,score_ref] = generate_nonstationary_renewal() # generate synthetic data: nonstationary renewal process.\n",
    "print('#######################################')\n",
    "print('## Non-tationary Renewal process')\n",
    "print('#######################################')\n",
    "print()\n",
    "\n",
    "\n",
    "########## Train and evaluate the model (The following code will raise warnings, but please ignore them.)\n",
    "\n",
    "# constant model\n",
    "npp1 = NPP(time_step=time_step,size_rnn=size_rnn,type_hazard='const').set_data(T).set_model().compile(lr=0.001).fit_eval(batch_size=256)\n",
    "\n",
    "# exponential model\n",
    "npp2 = NPP(time_step=time_step,size_rnn=size_rnn,type_hazard='exp').set_data(T).set_model().compile(lr=0.001).fit_eval(batch_size=256)\n",
    "\n",
    "# piecewise constant model\n",
    "npp3 = NPP(time_step=time_step,size_rnn=size_rnn,type_hazard='pc',size_div=size_div).set_data(T).set_model().compile(lr=0.001).fit_eval(batch_size=256)\n",
    "\n",
    "# neural network based model\n",
    "npp4 = NPP(time_step=time_step,size_rnn=size_rnn,type_hazard='NN',size_layer=size_layer,size_nn=size_nn).set_data(T).set_model().compile(lr=0.001).fit_eval(batch_size=256)\n",
    "\n",
    "print()\n",
    "print('#######################################')\n",
    "print('## Score')\n",
    "print('#######################################')\n",
    "print('## true model                 \\n score for the test data: %.3f' % score_ref)\n",
    "print('## constand model             \\n score for the test data: %.3f (standardized score: %.3f), loss for the validation data: %.3f' % (npp1.score,npp1.score-score_ref,npp1.val_loss) )\n",
    "print('## exponential model          \\n score for the test data: %.3f (standardized score: %.3f), loss for the validation data: %.3f' % (npp2.score,npp2.score-score_ref,npp2.val_loss) )\n",
    "print('## piecewise constant model   \\n score for the test data: %.3f (standardized score: %.3f), loss for the validation data: %.3f' % (npp3.score,npp3.score-score_ref,npp3.val_loss) )\n",
    "print('## neural network based model \\n score for the test data: %.3f (standardized score: %.3f), loss for the validation data: %.3f' % (npp4.score,npp4.score-score_ref,npp4.val_loss) )\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 577
    },
    "colab_type": "code",
    "executionInfo": {
     "elapsed": 1242133,
     "status": "ok",
     "timestamp": 1558483049476,
     "user": {
      "displayName": "O3 T",
      "photoUrl": "",
      "userId": "04273384571780432640"
     },
     "user_tz": -540
    },
    "id": "dbq6LRmK5W17",
    "outputId": "25c5c82d-ef97-4990-94fa-c0c87730ba4a"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "#######################################\n",
      "## Self-correcting process\n",
      "#######################################\n",
      "\n",
      "WARNING:tensorflow:Output \"subtract_16\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"subtract_16\".\n",
      "WARNING:tensorflow:Output \"layer_ll_12\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_12\".\n",
      "WARNING:tensorflow:Output \"layer_ll_12\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_12\".\n",
      "WARNING:tensorflow:Output \"subtract_17\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"subtract_17\".\n",
      "WARNING:tensorflow:Output \"layer_ll_13\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_13\".\n",
      "WARNING:tensorflow:Output \"layer_ll_13\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_13\".\n",
      "WARNING:tensorflow:Output \"subtract_18\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"subtract_18\".\n",
      "WARNING:tensorflow:Output \"layer_ll_14\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_14\".\n",
      "WARNING:tensorflow:Output \"layer_ll_14\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_14\".\n",
      "WARNING:tensorflow:Output \"subtract_19\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"subtract_19\".\n",
      "WARNING:tensorflow:Output \"lambda_29\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"lambda_29\".\n",
      "WARNING:tensorflow:Output \"dense_34\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"dense_34\".\n",
      "\n",
      "#######################################\n",
      "## Score\n",
      "#######################################\n",
      "## true model                 \n",
      " score for the test data: 0.761\n",
      "## constand model             \n",
      " score for the test data: 0.937 (standardized score: 0.176), loss for the validation data: 0.940\n",
      "## exponential model          \n",
      " score for the test data: 0.790 (standardized score: 0.029), loss for the validation data: 0.786\n",
      "## piecewise constant model   \n",
      " score for the test data: 0.804 (standardized score: 0.043), loss for the validation data: 0.801\n",
      "## neural network based model \n",
      " score for the test data: 0.791 (standardized score: 0.030), loss for the validation data: 0.785\n"
     ]
    }
   ],
   "source": [
    "########## Setup\n",
    "time_step = 20 # truncation depth of a RNN \n",
    "size_rnn = 64  # the number of units in a RNN\n",
    "size_div = 128 # the number of sub-intervals of the piecewise constant function (piecewise constant model)\n",
    "size_nn = 64   # the number of units in each hidden layer of the cumulative hazard function network (neural network based model)\n",
    "size_layer = 2 # the number of hidden layers of the cumulative hazard function network (neural network based model)\n",
    "\n",
    "########## Generate data\n",
    "[T,score_ref] = generate_self_correcting()       # generate synthetic data: self-correcting process.\n",
    "print('#######################################')\n",
    "print('## Self-correcting process')\n",
    "print('#######################################')\n",
    "print()\n",
    "\n",
    "\n",
    "########## Train and evaluate the model (The following code will raise warnings, but please ignore them.)\n",
    "\n",
    "# constant model\n",
    "npp1 = NPP(time_step=time_step,size_rnn=size_rnn,type_hazard='const').set_data(T).set_model().compile(lr=0.001).fit_eval(batch_size=256)\n",
    "\n",
    "# exponential model\n",
    "npp2 = NPP(time_step=time_step,size_rnn=size_rnn,type_hazard='exp').set_data(T).set_model().compile(lr=0.001).fit_eval(batch_size=256)\n",
    "\n",
    "# piecewise constant model\n",
    "npp3 = NPP(time_step=time_step,size_rnn=size_rnn,type_hazard='pc',size_div=size_div).set_data(T).set_model().compile(lr=0.001).fit_eval(batch_size=256)\n",
    "\n",
    "# neural network based model\n",
    "npp4 = NPP(time_step=time_step,size_rnn=size_rnn,type_hazard='NN',size_layer=size_layer,size_nn=size_nn).set_data(T).set_model().compile(lr=0.001).fit_eval(batch_size=256)\n",
    "\n",
    "print()\n",
    "print('#######################################')\n",
    "print('## Score')\n",
    "print('#######################################')\n",
    "print('## true model                 \\n score for the test data: %.3f' % score_ref)\n",
    "print('## constand model             \\n score for the test data: %.3f (standardized score: %.3f), loss for the validation data: %.3f' % (npp1.score,npp1.score-score_ref,npp1.val_loss) )\n",
    "print('## exponential model          \\n score for the test data: %.3f (standardized score: %.3f), loss for the validation data: %.3f' % (npp2.score,npp2.score-score_ref,npp2.val_loss) )\n",
    "print('## piecewise constant model   \\n score for the test data: %.3f (standardized score: %.3f), loss for the validation data: %.3f' % (npp3.score,npp3.score-score_ref,npp3.val_loss) )\n",
    "print('## neural network based model \\n score for the test data: %.3f (standardized score: %.3f), loss for the validation data: %.3f' % (npp4.score,npp4.score-score_ref,npp4.val_loss) )\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 577
    },
    "colab_type": "code",
    "executionInfo": {
     "elapsed": 1487556,
     "status": "ok",
     "timestamp": 1558483294909,
     "user": {
      "displayName": "O3 T",
      "photoUrl": "",
      "userId": "04273384571780432640"
     },
     "user_tz": -540
    },
    "id": "9P5AgYxD5XDz",
    "outputId": "35194a9f-32a2-4d3b-b3ff-b90a076b3649"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "#######################################\n",
      "## Hawkes1 process\n",
      "#######################################\n",
      "\n",
      "WARNING:tensorflow:Output \"subtract_20\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"subtract_20\".\n",
      "WARNING:tensorflow:Output \"layer_ll_15\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_15\".\n",
      "WARNING:tensorflow:Output \"layer_ll_15\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_15\".\n",
      "WARNING:tensorflow:Output \"subtract_21\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"subtract_21\".\n",
      "WARNING:tensorflow:Output \"layer_ll_16\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_16\".\n",
      "WARNING:tensorflow:Output \"layer_ll_16\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_16\".\n",
      "WARNING:tensorflow:Output \"subtract_22\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"subtract_22\".\n",
      "WARNING:tensorflow:Output \"layer_ll_17\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_17\".\n",
      "WARNING:tensorflow:Output \"layer_ll_17\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_17\".\n",
      "WARNING:tensorflow:Output \"subtract_23\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"subtract_23\".\n",
      "WARNING:tensorflow:Output \"lambda_35\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"lambda_35\".\n",
      "WARNING:tensorflow:Output \"dense_41\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"dense_41\".\n",
      "\n",
      "#######################################\n",
      "## Score\n",
      "#######################################\n",
      "## true model                 \n",
      " score for the test data: 0.466\n",
      "## constand model             \n",
      " score for the test data: 0.686 (standardized score: 0.219), loss for the validation data: 0.685\n",
      "## exponential model          \n",
      " score for the test data: 0.543 (standardized score: 0.076), loss for the validation data: 0.544\n",
      "## piecewise constant model   \n",
      " score for the test data: 0.482 (standardized score: 0.016), loss for the validation data: 0.477\n",
      "## neural network based model \n",
      " score for the test data: 0.479 (standardized score: 0.013), loss for the validation data: 0.479\n"
     ]
    }
   ],
   "source": [
    "########## Setup\n",
    "time_step = 20 # truncation depth of a RNN \n",
    "size_rnn = 64  # the number of units in a RNN\n",
    "size_div = 128 # the number of sub-intervals of the piecewise constant function (piecewise constant model)\n",
    "size_nn = 64   # the number of units in each hidden layer of the cumulative hazard function network (neural network based model)\n",
    "size_layer = 2 # the number of hidden layers of the cumulative hazard function network (neural network based model)\n",
    "\n",
    "########## Generate data\n",
    "[T,score_ref] = generate_hawkes1()               # generate synthetic data: hawkes1 process.\n",
    "print('#######################################')\n",
    "print('## Hawkes1 process')\n",
    "print('#######################################')\n",
    "print()\n",
    "\n",
    "\n",
    "########## Train and evaluate the model (The following code will raise warnings, but please ignore them.)\n",
    "\n",
    "# constant model\n",
    "npp1 = NPP(time_step=time_step,size_rnn=size_rnn,type_hazard='const').set_data(T).set_model().compile(lr=0.001).fit_eval(batch_size=256)\n",
    "\n",
    "# exponential model\n",
    "npp2 = NPP(time_step=time_step,size_rnn=size_rnn,type_hazard='exp').set_data(T).set_model().compile(lr=0.001).fit_eval(batch_size=256)\n",
    "\n",
    "# piecewise constant model\n",
    "npp3 = NPP(time_step=time_step,size_rnn=size_rnn,type_hazard='pc',size_div=size_div).set_data(T).set_model().compile(lr=0.001).fit_eval(batch_size=256)\n",
    "\n",
    "# neural network based model\n",
    "npp4 = NPP(time_step=time_step,size_rnn=size_rnn,type_hazard='NN',size_layer=size_layer,size_nn=size_nn).set_data(T).set_model().compile(lr=0.001).fit_eval(batch_size=256)\n",
    "\n",
    "print()\n",
    "print('#######################################')\n",
    "print('## Score')\n",
    "print('#######################################')\n",
    "print('## true model                 \\n score for the test data: %.3f' % score_ref)\n",
    "print('## constand model             \\n score for the test data: %.3f (standardized score: %.3f), loss for the validation data: %.3f' % (npp1.score,npp1.score-score_ref,npp1.val_loss) )\n",
    "print('## exponential model          \\n score for the test data: %.3f (standardized score: %.3f), loss for the validation data: %.3f' % (npp2.score,npp2.score-score_ref,npp2.val_loss) )\n",
    "print('## piecewise constant model   \\n score for the test data: %.3f (standardized score: %.3f), loss for the validation data: %.3f' % (npp3.score,npp3.score-score_ref,npp3.val_loss) )\n",
    "print('## neural network based model \\n score for the test data: %.3f (standardized score: %.3f), loss for the validation data: %.3f' % (npp4.score,npp4.score-score_ref,npp4.val_loss) )\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 577
    },
    "colab_type": "code",
    "executionInfo": {
     "elapsed": 1693382,
     "status": "ok",
     "timestamp": 1558483500746,
     "user": {
      "displayName": "O3 T",
      "photoUrl": "",
      "userId": "04273384571780432640"
     },
     "user_tz": -540
    },
    "id": "TJbi-kYg5XQh",
    "outputId": "121c9fc1-6ed0-4be2-e0af-da5d3b19987f"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "#######################################\n",
      "## Hawkes2 process\n",
      "#######################################\n",
      "\n",
      "WARNING:tensorflow:Output \"subtract_24\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"subtract_24\".\n",
      "WARNING:tensorflow:Output \"layer_ll_18\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_18\".\n",
      "WARNING:tensorflow:Output \"layer_ll_18\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_18\".\n",
      "WARNING:tensorflow:Output \"subtract_25\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"subtract_25\".\n",
      "WARNING:tensorflow:Output \"layer_ll_19\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_19\".\n",
      "WARNING:tensorflow:Output \"layer_ll_19\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_19\".\n",
      "WARNING:tensorflow:Output \"subtract_26\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"subtract_26\".\n",
      "WARNING:tensorflow:Output \"layer_ll_20\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_20\".\n",
      "WARNING:tensorflow:Output \"layer_ll_20\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"layer_ll_20\".\n",
      "WARNING:tensorflow:Output \"subtract_27\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"subtract_27\".\n",
      "WARNING:tensorflow:Output \"lambda_41\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"lambda_41\".\n",
      "WARNING:tensorflow:Output \"dense_48\" missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to \"dense_48\".\n",
      "\n",
      "#######################################\n",
      "## Score\n",
      "#######################################\n",
      "## true model                 \n",
      " score for the test data: 0.010\n",
      "## constand model             \n",
      " score for the test data: 0.681 (standardized score: 0.670), loss for the validation data: 0.681\n",
      "## exponential model          \n",
      " score for the test data: 0.422 (standardized score: 0.412), loss for the validation data: 0.420\n",
      "## piecewise constant model   \n",
      " score for the test data: 0.215 (standardized score: 0.204), loss for the validation data: 0.223\n",
      "## neural network based model \n",
      " score for the test data: 0.040 (standardized score: 0.029), loss for the validation data: 0.045\n"
     ]
    }
   ],
   "source": [
    "########## Setup\n",
    "time_step = 20 # truncation depth of a RNN \n",
    "size_rnn = 64  # the number of units in a RNN\n",
    "size_div = 128 # the number of sub-intervals of the piecewise constant function (piecewise constant model)\n",
    "size_nn = 64   # the number of units in each hidden layer of the cumulative hazard function network (neural network based model)\n",
    "size_layer = 2 # the number of hidden layers of the cumulative hazard function network (neural network based model)\n",
    "\n",
    "########## Generate data\n",
    "[T,score_ref] = generate_hawkes2() # generate synthetic data: hawkes2 process.\n",
    "print('#######################################')\n",
    "print('## Hawkes2 process')\n",
    "print('#######################################')\n",
    "print()\n",
    "\n",
    "\n",
    "########## Train and evaluate the model (The following code will raise warnings, but please ignore them.)\n",
    "\n",
    "# constant model\n",
    "npp1 = NPP(time_step=time_step,size_rnn=size_rnn,type_hazard='const').set_data(T).set_model().compile(lr=0.001).fit_eval(batch_size=256)\n",
    "\n",
    "# exponential model\n",
    "npp2 = NPP(time_step=time_step,size_rnn=size_rnn,type_hazard='exp').set_data(T).set_model().compile(lr=0.001).fit_eval(batch_size=256)\n",
    "\n",
    "# piecewise constant model\n",
    "npp3 = NPP(time_step=time_step,size_rnn=size_rnn,type_hazard='pc',size_div=size_div).set_data(T).set_model().compile(lr=0.001).fit_eval(batch_size=256)\n",
    "\n",
    "# neural network based model\n",
    "npp4 = NPP(time_step=time_step,size_rnn=size_rnn,type_hazard='NN',size_layer=size_layer,size_nn=size_nn).set_data(T).set_model().compile(lr=0.001).fit_eval(batch_size=256)\n",
    "\n",
    "print()\n",
    "print('#######################################')\n",
    "print('## Score')\n",
    "print('#######################################')\n",
    "print('## true model                 \\n score for the test data: %.3f' % score_ref)\n",
    "print('## constand model             \\n score for the test data: %.3f (standardized score: %.3f), loss for the validation data: %.3f' % (npp1.score,npp1.score-score_ref,npp1.val_loss) )\n",
    "print('## exponential model          \\n score for the test data: %.3f (standardized score: %.3f), loss for the validation data: %.3f' % (npp2.score,npp2.score-score_ref,npp2.val_loss) )\n",
    "print('## piecewise constant model   \\n score for the test data: %.3f (standardized score: %.3f), loss for the validation data: %.3f' % (npp3.score,npp3.score-score_ref,npp3.val_loss) )\n",
    "print('## neural network based model \\n score for the test data: %.3f (standardized score: %.3f), loss for the validation data: %.3f' % (npp4.score,npp4.score-score_ref,npp4.val_loss) )\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "VOVd8ZYt5gZz"
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "accelerator": "GPU",
  "colab": {
   "collapsed_sections": [],
   "name": "SupplementaryMaterial.ipynb",
   "provenance": [],
   "version": "0.3.2"
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
